package com.neusiri.service.impl;

import com.neusiri.contants.Contant;
import com.neusiri.entity.LoginRespEntity;
import com.neusiri.entity.SysUserEntity;
import com.neusiri.exception.BusinessException;
import com.neusiri.mapper.UserMapper;
import com.neusiri.service.RabbitmqService;
import com.neusiri.service.RedisService;
import com.neusiri.service.UserService;
import com.neusiri.util.CodeGenerateUtil;
import com.neusiri.util.PasswordUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * UserServiceImpl
 *
 * @author 丛有志
 * @date 2020/11/5 16:42
 * <p>
 * 版本        修改时间        作者        修改内容
 * V1.0        2020/11/5     丛有志        初始版本
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private RabbitmqService rabbitmqService;


    /**
     * 获取验证码
     *
     * @param phoneNumber 手机号码
     * @return 验证码
     */
    @Override
    public String getPicCode(String phoneNumber) {
        // 定义一天内手机最大发送次数
        int phoneMaxCount = 5;
        // 定义消息队列名称
        String routingKey = "hello";
        // 定义手机号正则
        String regex = "^1[3|4|5|7|8][0-9]{9}$";
        // 声名正则校验对象
        Pattern pattern = Pattern.compile(regex);
        // 校验手机号
        Matcher matcher = pattern.matcher(phoneNumber);
        // 判断手机号是否满足要求
        if (!matcher.matches()) {
            throw new BusinessException(4004, "手机号码格式错误");
        }
        // 判断手机号发送是否超限
        long count = redisService.incrby(Contant.REGISTER_CODE_COUNT_KEY + phoneNumber, 1);
        // 判断该手机号验证码是否发送达上限
        if (phoneMaxCount < count) {
            throw new BusinessException(4004, "当日发送已达上限");
        }
        // 生成6位随机数
        String picCode = CodeGenerateUtil.generatePicCode();
        // 用户存储消息队列信息
        Map<String,String> map = new HashMap<>(16);
        // 存放手机号码
        map.put("mobile",phoneNumber);
        // 存放验证码
        map.put("picCode",picCode);
        // 存到rabbitmq中-在消费者中发送短信
        rabbitmqService.publishHelloModel(routingKey,map);
        // 存入redis，过期时间为5分钟
        redisService.set(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY + phoneNumber, picCode, 5, TimeUnit.MINUTES);
        // 返回生成的验证码
        return picCode;
    }

    /**
     * 注册
     *
     * @param sysUserEntity 人员信息
     * @return 操作信息
     */
    @Override
    public String register(SysUserEntity sysUserEntity) {

        // 判断验证码是否有效
        if (!redisService.hasKey(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY + sysUserEntity.getPhone())) {
            throw new BusinessException(40001008, "验证码已失效请重新获取");
        }
        // 校验验证码是否正确
        if (!sysUserEntity.getPinCode().equals(redisService.get(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY + sysUserEntity.getPhone()))) {
            throw new BusinessException(40001009, "请输入正确验证码");
        }

        SysUserEntity userEntity = userMapper.getUserInfoByUserName(sysUserEntity.getUserName());
        if (null != userEntity) {
            throw new BusinessException(4001010, "该账号已被占用");
        }

        // 定义当前时间
        Date nowDate = new Date();
        // 生成UUID
        String userId = UUID.randomUUID().toString();
        // 生成盐值
        String salt = PasswordUtils.getSalt();
        // 设置用户id
        sysUserEntity.setId(userId);
        // 密码加密
        String encode = PasswordUtils.encode(sysUserEntity.getPassword(), salt);
        // 设置盐值
        sysUserEntity.setSalt(salt);
        // 设置密码
        sysUserEntity.setPassword(encode);
        // 设置修改时间
        sysUserEntity.setUpdateTime(nowDate);
        // 插入人员信息
        int i = userMapper.insertUserInfo(sysUserEntity);
        if (1 != i) {
            redisService.delete(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY + sysUserEntity.getPhone());
            redisService.delete(Contant.REGISTER_CODE_COUNT_KEY + sysUserEntity.getPhone());
            return "注册失败!";
        } else {
            return "注册成功！";
        }
    }


    /**
     * 登录
     *
     * @param sysUserEntity 人员信息
     * @return 登录响应信息
     */
    @Override
    public LoginRespEntity login(SysUserEntity sysUserEntity) {

        // 定义禁用状态码值
        Integer disableStatus = 2;
        //定义登录信息实体类
        LoginRespEntity loginRespEntity = new LoginRespEntity();
        //查询人员信息
        SysUserEntity userEntity = userMapper.getUserInfoByUserName(sysUserEntity.getUserName());
        // 判断用户是否存在
        if (null == userEntity) {
            throw new BusinessException(4004, "用户不存在！");
        } else {
            // 判断密码是否和密文匹配
            if (!PasswordUtils.matches(userEntity.getSalt(), sysUserEntity.getPassword(), userEntity.getPassword())) {
                throw new BusinessException(4004, "用户名密码不匹配");
                // 判断用户状态是否被禁用
            } else if (disableStatus.equals(userEntity.getStatus())) {
                throw new BusinessException(4004, "该用户已被禁用请联系管理员");
            } else {
                // 设置token值
                loginRespEntity.setToken(UUID.randomUUID().toString());
                // 设置用户id
                loginRespEntity.setId(userEntity.getId());
                // 将凭证存入redis60分钟失效
                redisService.set(loginRespEntity.getToken(), loginRespEntity.getId(), 60, TimeUnit.MINUTES);
                // 返回登录信息
                return loginRespEntity;
            }
        }
    }

    /**
     * 查询人员列表
     *
     * @return 人员列表
     */
    @Override
    public List<SysUserEntity> getUserInfoList() {
        return userMapper.getUserInfoList();
    }
}